package com.zeus.gen.base.dao.impl;

import com.zeus.gen.base.dto.Query;
import com.zeus.gen.base.dto.Query4Page;
import com.zeus.gen.base.exception.ZeusGenException;
import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.stereotype.Repository;
import com.zeus.gen.base.dao.MyBatisDao;
import com.zeus.gen.base.model.BaseModel;
import com.zeus.gen.util.ConversionUtil;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.List;
import java.util.Map;

/**
 * @author
 * @version 2018/1/18 下午2:54
 * @description 通用dao
 * @see
 * @since 1.0
 */
@Repository("myBatisDao")
public class MyBatisDaoImpl<T extends BaseModel> implements MyBatisDao<T> {

    public static final String SUFFIX_SAVE = ".save";
    public static final String SUFFIX_UPDATE = ".update";
    public static final String SUFFIX_UPDATE_SELECTIVE = ".updateSelective";
    public static final String SUFFIX_BATCH_UPDATE = ".batchUpdate";
    public static final String SUFFIX_DELETE = ".delete";
    public static final String SUFFIX_FIND = ".find";
    public static final String SUFFIX_COUNT = ".count";

    private static final String SP = ".";

    @Resource(name = "sqlSessionFactory")
    private SqlSessionFactory sqlSessionFactory;

    /**
     * 获取执行方法
     *
     * @param clazz
     * @param SUFFIX
     * @return
     */
    private String getStatement(Class<?> clazz, String SUFFIX) {
        if (StringUtils.isBlank(SUFFIX)) {
            throw new ZeusGenException("没有指定sqlId");
        }
        if (!SUFFIX.startsWith(SP)) {
            SUFFIX = SP + SUFFIX;
        }
        return clazz.getName() + SUFFIX;
    }

    @Override
    public <E> E findObjById(Class<T> clazz, Serializable id) {
        if (id == null) {
            return null;
        }
        Query query = new Query();
        query.append("id", id);
        return this.findObj(clazz, query, null);
    }


    @Override
    public <E> E findObj(Class<T> clazz, Query query, String sqlId) {
        if (StringUtils.isBlank(sqlId)) {
            sqlId = SUFFIX_FIND;
        }
        return sqlSessionFactory.openSession().selectOne(this.getStatement(clazz, sqlId), query);
    }

    @Override
    public <K,V> Map<K, V> findMap(Class<T> clazz, Query query, String sqlId, String mapKey) {
        if (StringUtils.isBlank(sqlId)) {
            throw new ZeusGenException("没有指定sqlId");
        }
        return sqlSessionFactory.openSession().selectMap(this.getStatement(clazz, sqlId), query, mapKey);
    }


    @Override
    public <E> List<E> findList(Class<T> clazz, Query query, String sqlId, boolean includeCount) {
        if (StringUtils.isBlank(sqlId)) {
            sqlId = SUFFIX_FIND;
        }
        if (query instanceof Query4Page && includeCount) {
            int count = this.count(clazz, query, SUFFIX_COUNT);
            if (count > 0) {
                Query4Page query4Page = (Query4Page) query;
                query4Page.setMaxRowCount(count);
                query4Page.setMaxPage();
                query = query4Page;
            }
        }
        return sqlSessionFactory.openSession().selectList(this.getStatement(clazz, sqlId), query);
    }

    @Override
    public int count(Class<T> clazz, Query query, String sqlId) {
        if (StringUtils.isBlank(sqlId)) {
            sqlId = SUFFIX_COUNT;
        }
        return sqlSessionFactory.openSession().selectOne(this.getStatement(clazz, sqlId), query);
    }

    @Override
    public int save(T obj, String sqlId) {
        if (StringUtils.isBlank(sqlId)) {
            sqlId = SUFFIX_SAVE;
        }
        return sqlSessionFactory.openSession().insert(this.getStatement(obj.getClass(), sqlId), obj);
    }


    @Override
    public int update(T obj, String sqlId) {
        if (StringUtils.isBlank(sqlId)) {
            sqlId = SUFFIX_UPDATE;
        }
        return sqlSessionFactory.openSession().update(this.getStatement(obj.getClass(), sqlId), obj);
    }

    @Override
    public int updateSelective(T obj, String sqlId) {
        if (StringUtils.isBlank(sqlId)) {
            sqlId = SUFFIX_UPDATE_SELECTIVE;
        }
        return sqlSessionFactory.openSession().update(this.getStatement(obj.getClass(), sqlId), obj);
    }

    @Override
    public int batchUpdate(Class<T> clazz, List<? extends Serializable> idList, Object obj, String sqlId) {
        if (StringUtils.isBlank(sqlId)) {
            sqlId = SUFFIX_BATCH_UPDATE;
        }
        Map<String, Object> map;
        try {
            map = ConversionUtil.conversionToMapExcludeEmpty(obj);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        map.put("idList", idList);
        return sqlSessionFactory.openSession().update(this.getStatement(clazz, sqlId), map);
    }

    @Override
    public int delete(Class<T> clazz, Serializable id, String sqlId) {
        if (StringUtils.isBlank(sqlId)) {
            sqlId = SUFFIX_DELETE;
        }
        return sqlSessionFactory.openSession().delete(this.getStatement(clazz, sqlId), id);
    }

    @Override
    public int delete(T obj, String sqlId) {
        if (StringUtils.isBlank(sqlId)) {
            sqlId = SUFFIX_DELETE;
        }
        return sqlSessionFactory.openSession().delete(this.getStatement(obj.getClass(), sqlId), obj);
    }

}
